package graphics;

import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.glClear;
import static org.lwjgl.opengl.GL11.glPopMatrix;
import static org.lwjgl.opengl.GL11.glPushMatrix;
import static org.lwjgl.opengl.GL11.glTranslatef;
import graphics.object.interfaces.GLKeyboardListener;
import graphics.object.interfaces.GLMouseListener;
import graphics.object.interfaces.GLRenderableObject;
import graphics.object.interfaces.GLTextListener;
import graphics.object.interfaces.GLTickListener;

import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;

public class GLEventManager {

    public GLEventManager(){}

    /**
     * Called when a mouse button was released.
     * @param button - ID of the button released.
     * @param x - x position of the mouse.
     * @param y - y position of the mouse.
     */
    public void eventMouseRelease(int button, int x, int y){
        if(button == -1){
            return;
        }
        for(GLMouseListener a : TestingGraphics.objectManager.listenerMouseObjects){
            a.onMouseRelease(button, x, y);
        }
    }

    /**
     * Called when a mouse button was pressed.
     * @param button - ID of the button pressed.
     * @param x - x position of the mouse.
     * @param y - y position of the mouse.
     */
    public void eventMousePress(int button, int x, int y){
        System.out.println("MOUSE: ID: " + button + " X: " + x + " Y: " + y);
        for(GLMouseListener a : TestingGraphics.objectManager.listenerMouseObjects){
            a.onMousePress(button, x, y);
        }
    }

    /**
     * Called when the mouse's position is changed.
     * @param x - x position of the mouse.
     * @param y - y position of the mouse.
     * @param dx - x position movement from the last position.
     * @param dy - y position movement from the last position.
     */
    public void eventMouseMove(int x, int y, int dx, int dy){
        //This if statement makes sure the dx and dy don't 'freakout' when the mouse moves out of the frame.
        //It causes some issues but overall improves stability.
        if(!(Mouse.getX() > 0 && Mouse.getX() < (TestingGraphics.width - 1)) || !(Mouse.getY() > 0 && Mouse.getY() < (TestingGraphics.height - 1))){
            return;
        }
        if(Mouse.isButtonDown(1)){
            TestingGraphics.translate_x += dx;
            TestingGraphics.translate_y -= dy;
            dy = 0;
            dx = 0;
        }
        for(GLMouseListener a : TestingGraphics.objectManager.listenerMouseObjects){
            a.onMouseMove(x, y, dx, dy);
        }
    }

    /**
     * Called when a key on the keyboard is pressed.
     * @param id - id of the key pressed.
     */
    public void eventKeyPressed(int id){
        System.out.println("KEY: ID: " + id + " N: " + Keyboard.getKeyName(id));

        for(GLKeyboardListener a : TestingGraphics.objectManager.listenerKeyboardObjects){
            a.onKeyPress(id);
        }
    }

    /**
     * Called when a key on the keyboard is released.
     * @param id - id of the key released.
     */
    public void eventKeyReleased(int id){
        if(Keyboard.KEY_ESCAPE == id){
            Display.destroy();
            System.exit(0);
        }

        for(GLKeyboardListener a : TestingGraphics.objectManager.listenerKeyboardObjects){
            a.onKeyRelease(id);
        }
    }

    /**
     * Called  by the TextInputManager. Is called when the user types a character that is visable. 
     * @param input - Text that the user entered after the TextInputManager formatted it.
     */
    public void eventTextInput(String input){
        for(GLTextListener a : TestingGraphics.objectManager.listenerTextObjects){
            a.onTextInput(input);
        }
    }

    /**
     * Called before the frame is rendered and before input is checked.
     */
    public void eventTick(long currentTime, long deltaTime){
        for(GLTickListener a : TestingGraphics.objectManager.listenerTickObjects){
            a.onTick(currentTime, deltaTime);
        }
    }

    /**
     * Called while the frame is being rendered.
     */
    public void eventRender(){
    	glClear(GL_COLOR_BUFFER_BIT);
        glPushMatrix();

        glTranslatef(TestingGraphics.translate_x, TestingGraphics.translate_y, 0);

        for(GLRenderableObject a : TestingGraphics.objectManager.renderableObjects){
            a.onRender();
        }
        
        glPopMatrix();
    }
}
